const ArticleModel = require('@/models/article.model')
const JsonResult = require('@/utils/httpResponse.unit')
const DynamicsModel = require('@/models/dynamics.model')
const { getSessionuserId } = require('@/utils/common.util')
const { exportWebPageToPDF, exportWebPageToJPG, exportWebArticleToMd } = require('@/utils/exportFile')
const UserCollectArticleModel = require('@/models/user_collect_article.model')
const MessageModel = require('@/models/message.model')
const UserModel = require('@/models/user.model')
const { setexAsync, getAsync } = require('@/redis')

const APIMAP = {
  PDF: exportWebPageToPDF,
  JPG: exportWebPageToJPG,
  Markdown: exportWebArticleToMd
}

class ArticleController {
  /**
   * search articles has passed
   * @param {*} req
   * @param {*} response
   */
  async getAllArticles (req, response) {
    try {
      const sessionId = await getSessionuserId(req)
      const { pageNo, pageSize, category, sort = 'new' } = req.query
      const data = await ArticleModel.find({
        pageNo,
        pageSize,
        category: category === 'focus' ? '' : category,
        sort,
        isFocus: category === 'focus',
        'article.status': '2'
      }, sessionId)
      JsonResult.success({
        req,
        response,
        data,
        message: '查询文章列表成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询文章列表失败' })
    }
  }

  /**
   * search articles by userId
   * @param {*} req
   * @param {*} response
   */
  async getArticlesByUserId (req, response) {
    const sessionId = await getSessionuserId(req)
    const { pageNo, pageSize, userId } = req.query
    try {
      const data = await ArticleModel.find({
        pageNo,
        pageSize,
        sort: 'new',
        'article.userId': userId,
        'article.status': userId === sessionId ? null : '2'
      }, sessionId)
      JsonResult.success({
        req,
        response,
        data,
        message: '查询文章列表成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询文章列表失败' })
    }
  }

  /**
   * search articleInfo
   * @param {*} req
   * @param {*} response
   */
  async getArticleInfo (req, response) {
    try {
      const articleId = req.query.id
      const sessionId = await getSessionuserId(req)
      const data = await ArticleModel.findOne(articleId, sessionId, true)
      if (data.status !== '2' && sessionId !== data.userId) {
        return JsonResult.success({
          req,
          response,
          message: '无权限查看此文章'
        })
      }
      ArticleModel.autoIncre(articleId, 'viewCounts')
      JsonResult.success({
        req,
        response,
        data,
        message: '查询文章详情成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询文章详情失败' })
    }
  }

  /**
   * search article md
   * @param {*} req
   * @param {*} response
   */
  async getArticleMarkdown (req, response) {
    try {
      const articleId = req.query.id
      const sessionId = req.sessionuser.id
      const data = await ArticleModel.findOne(articleId, sessionId)
      if (data.userId !== sessionId) {
        return JsonResult.httpStatus(req, response, 403, {
          message: 'No permission to see article',
          code: '9999'
        })
      }
      JsonResult.success({
        req,
        response,
        data,
        message: '获取文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '获取文章失败' })
    }
  }

  /**
   * create article
   * @param {*} req
   * @param {*} response
   */
  async createArticle (req, response) {
    try {
      const userId = req.sessionuser.id
      const articleId = await ArticleModel.create(req.body, userId)
      DynamicsModel.add({ userId, type: '1', articleId })
      JsonResult.success({
        req,
        response,
        message: '发布文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '发布文章失败' })
    }
  }

  /**
   * update article
   * @param {*} req
   * @param {*} response
   */
  async updateArticle (req, response) {
    try {
      const id = req.body.id
      const articleInfo = await ArticleModel.exists({ id })
      if (articleInfo.userId !== req.sessionuser.id) {
        return JsonResult.httpStatus(req, response, 403, {
          message: 'No permission to edit article',
          code: '9999'
        })
      }
      await ArticleModel.update(req.body, id)
      JsonResult.success({
        req,
        response,
        message: '更新文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '更新文章失败' })
    }
  }

  /**
   * delete article
   * @param {*} req
   * @param {*} response
   * @returns
   */
  async deleteArticle (req, response) {
    try {
      const id = req.query.id
      const articleInfo = await ArticleModel.exists({ id })
      if (!articleInfo) {
        JsonResult.fail({ req, response, message: '文章不存在' })
      }
      if (articleInfo.userId !== req.sessionuser.id) {
        return JsonResult.httpStatus(req, response, 403, {
          message: 'No permission to delete article',
          code: '9999'
        })
      }
      await ArticleModel.delete(id)
      await UserCollectArticleModel.delete({ articleId: id })
      DynamicsModel.delete({ articleId: id })
      JsonResult.success({
        req,
        response,
        message: '删除文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '删除文章失败' })
    }
  }

  /**
   * get articles by collect
   * @param {*} req
   * @param {*} response
   */
  async getArticleByCollect (req, response) {
    try {
      const { userId } = req.query
      const sessionId = await getSessionuserId(req)
      const data = await ArticleModel.findUserCollectArticle(userId, sessionId)
      JsonResult.success({
        req,
        response,
        data,
        message: '查询收藏文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询收藏文章失败' })
    }
  }

  /**
   * get articles by agree
   * @param {*} req
   * @param {*} response
   */
  async getArticleByAgree (req, response) {
    try {
      const { userId } = req.query
      const sessionId = await getSessionuserId(req)
      const data = await ArticleModel.findUserAgreeArticle(userId, sessionId)
      JsonResult.success({
        req,
        response,
        data,
        message: '查询点赞文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询点赞文章失败' })
    }
  }

  /**
   * export article file
   * @param {*} req
   * @param {*} response
   * @returns
   */
  async exportArticle (req, response) {
    try {
      const { articleId, exportType } = req.body
      const articleInfo = await ArticleModel.exists({ id: articleId })
      if (!articleInfo) {
        JsonResult.fail({ req, response, message: '文章不存在' })
      }
      if (articleInfo.userId !== req.sessionuser.id) {
        return JsonResult.httpStatus(req, response, 403, {
          message: 'No permission to export article',
          code: '9999'
        })
      }
      const API = APIMAP[exportType]
      const articleBuffer = await API({
        url: `http://localhost:8088/preview-pdf/${articleId}`,
        md: articleInfo.content
      })
      response.set({
        'Content-Type': 'application/octec-stream',
        'Content-Disposition': 'attachment;'
      })
      response.write(articleBuffer)
      response.end()
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '导出失败' })
    }
  }

  /**
   * find user recommend articles
   * @param {*} req
   * @param {*} response
   */
  async findRecommendArticles (req, response) {
    try {
      const sessionId = await getSessionuserId(req)
      const tags = req.body.tags
      const filterId = req.body.articleId || ''
      const data = await ArticleModel.findRecommend(tags.split(';'), sessionId, filterId)
      JsonResult.success({
        req,
        response,
        data,
        message: '查询推荐文章成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询失败' })
    }
  }

  async getAuthorRecommendArticles (req, response) {
    try {
      const { userId, articleId } = req.body
      const cache = await getAsync(`${userId}-${articleId}`)
      const data = cache ? JSON.parse(cache) : await ArticleModel.findAuthorRecommend(userId, articleId)
      !cache && setexAsync(`${userId}-${articleId}`, 60 * 60 * 24, JSON.stringify(data))
      JsonResult.success({
        req,
        response,
        data,
        message: '查询成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '查询失败' })
    }
  }

  async setArticleTop (req, response) {
    const { articleId, type } = req.query
    const topTimeStap = type === 'set' ? new Date().getTime() : null
    try {
      await ArticleModel.setTop(articleId, topTimeStap)
      JsonResult.success({
        req,
        response,
        message: '置顶成功'
      })
    } catch (error) {
      JsonResult.fail({ req, response, error, message: '置顶失败' })
    }
  }

  /**
   * 文章审核结果
   * @param {*} req
   * @param {*} response
   */
  async approvelResult (req, response) {
    const { articleId, status, reason } = req.body
    try {
      const articleInfo = await ArticleModel.exists({ id: articleId })
      if (!articleInfo) {
        JsonResult.fail({ req, response })
      }
      const { articleTitle, userId } = articleInfo
      const resultText = status === '2' ? '已经审核通过。' : '审核不通过。'
      const content = `你发布的文章<a href="/post/${articleId}" target="_blank">${articleTitle}</a>${resultText} ${status === '2' ? '赶紧去看看吧！' : `<p class="reason">不通过原因：<span>${reason}</span></p>`}`
      await MessageModel.add({ sourceUserId: '1', targetUserId: userId, articleId, itemType: '5', content })
      if (status === '2') {
        // 经验值增加
        UserModel.updateExp(userId, 5)
      }
      JsonResult.success({
        req,
        response
      })
    } catch (error) {
      JsonResult.fail({ req, response, error })
    }
  }
}

module.exports = new ArticleController()
